package threads;


import java.util.Random;

/**此例子是一个生产者与消费者线程问题
 * 描述:生产者不断往仓库中方东西，消费者不断往仓库拿东西
 * 仓库规则：仓库容量有限，库满时不能存放，库空时不能取产品*/
public class Product {
    private int id;
    private String name;
    public Product(int id,String name)
    {
        this.id=id;
        this.name=name;
    }
    public String toString()
    {
        return "(产品id:"+id+"产品名称:"+name+")";
    }
    public int getId()
    {
        return  id;
    }
    public void setId()
    {
        this.id=id;
    }
    public String getName()
    {
        return name;
    }
    public void setName()
    {
        this.name=name;
    }



    //产品类
    public static void main(String [] args)throws InterruptedException
    {
        //主函数抛出中断异常
        Storage storage=new Storage();
        Thread consumer1=new Thread(new Consumer(storage));
        consumer1.setName("生产者1");
        Thread consumer2=new Thread(new Consumer(storage));
        consumer1.setName("生产者2");
        Thread producer1=new Thread(new Producer(storage));
        producer1.setName("消费者1");
        Thread producer2=new Thread(new Producer(storage));
        producer1.setName("消费者2");
        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();

    }

}

class Storage
{
    //定义仓库类
    private Product[] products=new Product[10];//定义仓库大小
    private int top=0;//指现在当前得位置，即产品得数量
    public synchronized void push(Product product) throws InterruptedException {
        //用锁修饰的方法，往仓库里放东西
        while(top==products.length)
        {//仓库满了说明数组容量为零
            System.out.println("仓库已满,生产者请等待");
            wait();//仓库满了，等待；用到中断处理
        }
        top+=1;
        products[top]=product;//把产品放到仓库的top++位置上
        System.out.println(Thread.currentThread().getName()+"生产了产品"+product);
        notifyAll();//唤醒全部的等待的线程
    }
    public synchronized Product pop()
    {
        //用锁修饰方法，往仓库中拿出东西
        //仓库为空的时候不可以拿，即没有产品
        while(top==0)
        {
            System.out.println("仓库为空，消费者请等待");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //另外一种情况就是把仓库看成是有货物的
        top--;
        Product p=new Product(products[top].getId(),products[top].getName());
        products[top]=null;
        System.out.println(Thread.currentThread().getName()+"消费了产品"+p);
        System.out.println("消费者等待");
        notifyAll();
        return p;
    }


}
class Producer implements Runnable
{
    private Storage storage;
    public Producer(Storage storage)
    {
        this.storage=storage;
    }
    public void run()
    {
        int i=0;
        Random r=new Random();
        while(i<10)
        {
            i++;
            Product product=new Product(i,"电话："+r.nextInt(100));
            try {
                storage.push(product);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Consumer implements Runnable
{
    //消费者方法
    private Storage storage;
    public Consumer(Storage storage)
    {
        this.storage=storage;
    }
    public void run()
    {
        int i=0;
        while(i<10)
        {
            i++;
            storage.pop();
        }


    }
}
